# -*- coding:utf-8 -*-
import os,sys
import subprocess
from app.common.const_value import TargetLanguage

class ExportService:
    """
    导出主业务逻辑
    """
    def __init__(self, controller):
        # 控制器（能操作到view 和 model）
        self.controller = controller

    def _generate_protoc_command(self,
        protoc_cmd:str,
        proto_dir: str,
        output_dir: str,
        target_lang: TargetLanguage,
        proto_files: list,
        include_dirs: list = None,
        extra_options: list = None
    ) -> list:
        """
        生成 protoc 命令参数列表
        
        :param proto_dir: proto 文件所在目录
        :param output_dir: 输出目录
        :param target_lang: 目标语言
        :param proto_files: 要处理的 proto 文件列表
        :param include_dirs: 额外的导入目录
        :param extra_options: 额外的 protoc 选项
        :return: 完整的 protoc 命令参数列表
        """
        command = []
        # 基础命令
        command.append(protoc_cmd)
        # 添加导入路径 (proto_path)
        command.append(f"--proto_path={proto_dir}")
        if include_dirs:
            for include_dir in include_dirs:
                command.append(f"--proto_path={include_dir}")
        # 添加语言特定的输出选项
        lang_option = f"--{target_lang.value}_out"
        # 特殊处理 TypeScript
        if target_lang == TargetLanguage.TYPESCRIPT:
            lang_option = "--ts_out"
        # 添加输出目录
        command.append(f"{lang_option}={output_dir}")
        # 添加额外选项
        if extra_options:
            command.extend(extra_options)
        # 添加所有 proto 文件
        command.extend(proto_files)

        return command

    def run_protoc(self, command: list) -> bool:
        """
        执行 protoc 命令
        
        :param command: protoc 命令参数列表
        :return: 是否成功
        """
        self.controller.add_log("\n🔧 执行命令: " + " ".join(command))
        try:
            result = subprocess.run(
                command,
                capture_output=True,
                text=True,
                check=True
            )
            # 输出结果
            if result.stdout:
                self.controller.add_log("📋 输出信息:")
                self.controller.add_log(result.stdout)
            self.controller.add_log("✅ 转换成功!")
            return True
        except subprocess.CalledProcessError as e:
            self.controller.add_log(f"❌ 转换失败 (错误码: {e.returncode})")
            if e.stderr:
                self.controller.add_log("\n🛑 错误信息:")
                self.controller.add_log(e.stderr)
            
            if e.stdout:
                self.controller.add_log("\n📋 输出信息:")
                self.controller.add_log(e.stdout)
            return False

    def _get_protoc_cmd(self):
        if sys.platform.startswith('win'):
            self.controller.add_log("当前系统：Windows")
            return "protoc.exe"
        elif sys.platform.startswith('linux'):
            self.controller.add_log("当前系统：Linux")
            return "protoc"
        else:
            self.controller.add_log(f"未知系统：{sys.platform}")
            return ""

    def _get_export_type(self, export_type: str) -> TargetLanguage:
        """
        根据导出类型字符串获取 TargetLanguage 枚举值
        
        :param export_type: 导出类型字符串
        """
        if export_type == TargetLanguage.CPP.value:
            return TargetLanguage.CPP
        elif export_type == TargetLanguage.JAVA.value:
            return TargetLanguage.JAVA
        elif export_type == TargetLanguage.PYTHON.value:
            return TargetLanguage.PYTHON
        elif export_type == TargetLanguage.GO.value:
            return TargetLanguage.GO
        elif export_type == TargetLanguage.CSHARP.value:
            return TargetLanguage.CSHARP
        else:
            self.controller.add_log(f"未知导出类型: {export_type}")
            return None

    def export(self):
        """
        根据mode中的数据，组织调用系统命令，然后执行
        实现具体导出的方法,参数说明:
            protoc_dir 
            proto_dir 
            server_export_type 
            server_dir 
            client_export_type 
            client_dir 
        """
        protoc_dir = self.controller.model.protoc_dir()
        proto_dir = self.controller.model.proto_dir()
        server_export_type = self.controller.model.server_export_type()
        server_dir = self.controller.model.server_dir()
        client_export_type = self.controller.model.client_export_type()
        client_dir = self.controller.model.client_dir()
        # 检查 protoc 路径，是否命令存在
        if not os.path.exists(protoc_dir):
            self.controller.add_log(f"❌ Protoc 路径不存在: {protoc_dir}")
            return False
        protoc_cmd = os.path.join(protoc_dir, self._get_protoc_cmd())
        if not os.path.isfile(protoc_cmd):
            self.controller.add_log(f"❌ Protoc 命令不存在: {protoc_cmd}")
            return False 
        # 获取 proto 文件列表
        proto_files = [f for f in os.listdir(proto_dir) if f.endswith('.proto')]
        if not proto_files:
            self.controller.add_log(f"❌ 没有找到 proto 文件在目录: {proto_dir}")
            return False
        # 遍历proto文件列表，执行转换
        for proto_file in proto_files:
            proto_file_path = os.path.join(proto_dir, proto_file)
            if not os.path.isfile(proto_file_path):
                self.controller.add_log(f"❌ 找不到 proto 文件: {proto_file_path}")
                continue
            
            # 生成服务端代码
            server_command = self._generate_protoc_command(
                protoc_cmd=protoc_cmd,
                proto_dir=proto_dir,
                output_dir=server_dir,
                target_lang= self._get_export_type(server_export_type),
                proto_files=[proto_file_path]
            )
            self.run_protoc(server_command)

            # 生成客户端代码
            client_command = self._generate_protoc_command(
                protoc_cmd=protoc_cmd,
                proto_dir=proto_dir,
                output_dir=client_dir,
                target_lang= self._get_export_type(client_export_type),
                proto_files=[proto_file_path]
            )
            self.run_protoc(client_command) 